// my_predictor.h - Daan Raman
// A local bimodal predictor.

class my_update : public branch_update {
public:
	unsigned int index;
	unsigned int address;
}; 

class my_predictor : public branch_predictor {
public:
	
#define INDEX_BITS 13
	
	my_update u;
	branch_info bi;
	unsigned int counters[1<<INDEX_BITS];
	unsigned int cIndex;
	
	my_predictor (void) { 
		//nothing to do here
	}
	
	branch_update *predict (branch_info & b) {
		bi = b;
		if (b.br_flags & BR_CONDITIONAL) {
			//Save jump address
			u.address = b.address;
			cIndex = u.address & ((1<< (INDEX_BITS)) -1);
			
			//printf("***********************\n");
			//printf("ADDRESS IN PREDICTOR - 0x%08x \n", u.address);
			//printf("INDEX BITS           - 0x%08x \n", u.address & (1<< (INDEX_BITS)) -1);
			//printf("***********************\n");
			
			if(counters[cIndex] >= 2){
				u.direction_prediction(true);
			}else{
				u.direction_prediction(false);
			}
		} else {
			u.direction_prediction (true);
		}
		u.target_prediction (0);
		return &u;
	}
	
	void update (branch_update *u, bool taken, unsigned int target) {
		if (bi.br_flags & BR_CONDITIONAL) {
			
			cIndex = ((my_update*)u)->address & (1<< (INDEX_BITS)) -1;
			
			if (taken) {
				if(counters[cIndex] < 3){
					counters[cIndex]++;
				}
			} else {
				if(counters[cIndex] >0){
					counters[cIndex]--;
				}
			}
			
			//printf("%d", counters[cIndex]);
			
		}
	}
	
	void bin (int num) 
	{ 
		while (num != 0) 
		{ 
			printf ("%d",num % 2); 
			num = num /2; 
		} 
		
		printf("\n");
	}
	
};